package com.yonyou.test;


import java.security.Key;
import java.security.KeyFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;

public class YhtSimpleRsaUtils {
    public static final String KEY_ALGORITHM = "RSA";

    public static String decrypt(String data, String privateKey) {
        try {
            return new String(
                    decryptByPrivateKey(decryptBASE64(data), privateKey));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static byte[] decryptBASE64(String key) {
        return Base64.decodeBase64(key.getBytes());
    }

    public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception {
        byte[] keyBytes = decryptBASE64(key);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        return decryptByPrivateKey(data, privateKey);
    }

    public static byte[] decryptByPrivateKey(byte[] data, Key privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(2, privateKey);
        byte[] inputArray = data;
        int inputLength = inputArray.length;
        int maxEncryptBlock = 128;
        int offSet = 0;
        byte[] resultBytes = new byte[0];
        byte[] cache = new byte[0];
        while (inputLength - offSet > 0) {
            if (inputLength - offSet > maxEncryptBlock) {
                cache = cipher.doFinal(inputArray, offSet, maxEncryptBlock);
                offSet += maxEncryptBlock;
            } else {
                cache = cipher.doFinal(inputArray, offSet, inputLength - offSet);
                offSet = inputLength;
            }
            resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
            System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
        }
        return resultBytes;
    }

    public static String encrypt(String data, String publicKey) {
        try {
            return encryptBASE64(encryptByPublicKey(data, publicKey));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String encryptBASE64(byte[] bytes) {
        return new String(Base64.encodeBase64(bytes));
    }

    public static byte[] encryptByPublicKey(String data, String key) throws Exception {
        byte[] keyBytes = decryptBASE64(key);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key publicKey = keyFactory.generatePublic(x509KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(1, publicKey);
        byte[] inputArray = data.getBytes();
        int inputLength = inputArray.length;
        int maxEncryptBlock = 117;
        int offSet = 0;
        byte[] resultBytes = new byte[0];
        byte[] cache = new byte[0];
        while (inputLength - offSet > 0) {
            if (inputLength - offSet > maxEncryptBlock) {
                cache = cipher.doFinal(inputArray, offSet, maxEncryptBlock);
                offSet += maxEncryptBlock;
            } else {
                cache = cipher.doFinal(inputArray, offSet, inputLength - offSet);
                offSet = inputLength;
            }
            resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
            System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
        }
        return resultBytes;
    }
}